1 #import "AMPurpleJabberAdHocServer.h"
2 #import "ESPurpleJabberAccount.h"
3 #import "AMPurpleJabberFormGenerator.h"
4 #import "AMPurpleJabberAdHocCommand.h"
5 #include <Libpurple/jabber.h>
7 @interface AMPurpleJabberAdHocServer (PRIVATE)
8 - (BOOL)receivedCommand:(xmlnode*)command from:(NSString*)jid iqid:(NSString*)iqid;
9 - (void)addCommandsToXML:(xmlnode*)xml;
12 @implementation AMPurpleJabberAdHocServer
14 static void AMPurpleJabberAdHocServer_received_data_cb(PurpleConnection *gc, xmlnode **packet, gpointer this) {
15 AMPurpleJabberAdHocServer *self = this;
16 PurpleAccount *account = [[self account] purpleAccount];
17 if(account->gc == gc) {
18 if(strcmp((*packet)->name,"iq"))
20 const char *type = xmlnode_get_attrib(*packet,"type");
21 if(!type || strcmp(type,"set"))
22 return; // doesn't talk to us, probably the user interacting with some other adhoc node
23 const char *from = xmlnode_get_attrib(*packet,"from");
24 const char *iqid = xmlnode_get_attrib(*packet,"id");
25 xmlnode *command = xmlnode_get_child_with_namespace(*packet,"command","http://jabber.org/protocol/commands");
27 BOOL handled = [self receivedCommand:command
28 from:from?[NSString stringWithUTF8String:from]:nil
29 iqid:iqid?[NSString stringWithUTF8String:iqid]:nil];
31 xmlnode_free(*packet);
38 /* we have to catch the reply to a disco#info for http://jabber.org/protocol/commands and insert our nodes */
39 static void xmlnode_sent_cb(PurpleConnection *gc, xmlnode **packet, gpointer this) {
40 xmlnode *xml = *packet;
41 AMPurpleJabberAdHocServer *self = this;
42 PurpleAccount *account = [[self account] purpleAccount];
43 if(xml && account->gc == gc) {
44 if(!strcmp(xml->name,"iq")) {
45 const char *tostr = xmlnode_get_attrib(xml,"to");
47 NSString *to = [NSString stringWithUTF8String:tostr];
48 NSRange slash = [to rangeOfString:@"/"];
49 if(slash.location != NSNotFound) {
50 NSString *barejid = [to substringToIndex:slash.location];
51 if([barejid isEqualToString:[[self account] UID]]) {
52 const char *type = xmlnode_get_attrib(xml,"type");
53 if(type && !strcmp(type,"result")) {
54 xmlnode *query = xmlnode_get_child_with_namespace(xml,"query","http://jabber.org/protocol/disco#items");
56 const char *node = xmlnode_get_attrib(query,"node");
57 if(node && !strcmp(node,"http://jabber.org/protocol/commands"))
58 [self addCommandsToXML:query];
69 jabber_add_feature("adiumcmd", "http://jabber.org/protocol/commands", NULL);
72 - (id)initWithAccount:(ESPurpleJabberAccount*)_account {
73 if((self = [super init])) {
75 commands = [[NSMutableDictionary alloc] init];
77 PurplePlugin *jabber = purple_find_prpl("prpl-jabber");
79 AILog(@"Unable to locate jabber prpl");
84 purple_signal_connect(jabber, "jabber-receiving-xmlnode", self,
85 PURPLE_CALLBACK(AMPurpleJabberAdHocServer_received_data_cb), self);
86 purple_signal_connect(jabber, "jabber-sending-xmlnode", self,
87 PURPLE_CALLBACK(xmlnode_sent_cb), self);
93 purple_signals_disconnect_by_handle(self);
98 - (void)addCommand:(NSString*)node delegate:(id)delegate name:(NSString*)name {
99 [commands setObject:[NSDictionary dictionaryWithObjectsAndKeys:
100 [NSValue valueWithNonretainedObject:delegate],@"delegate",
105 - (void)removeCommand:(NSString*)node {
106 [commands removeObjectForKey:node];
109 - (ESPurpleJabberAccount*)account {
113 - (void)addCommandsToXML:(xmlnode*)xml {
114 NSEnumerator *e = [commands keyEnumerator];
116 JabberStream *js = purple_account_get_connection([[self account] purpleAccount])->proto_data;
117 char *jid = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource);
119 while((node = [e nextObject])) {
120 xmlnode *item = xmlnode_new_child(xml, "item");
121 xmlnode_set_attrib(item,"jid",jid);
122 xmlnode_set_attrib(item,"name",[[[commands objectForKey:node] objectForKey:@"name"] UTF8String]);
123 xmlnode_set_attrib(item,"node",[node UTF8String]);
128 - (BOOL)receivedCommand:(xmlnode*)command from:(NSString*)jid iqid:(NSString*)iqid {
129 // verify that it's the same bare jid this command was received from
132 NSRange slash = [jid rangeOfString:@"/"];
133 if(slash.location == NSNotFound || ![[jid substringToIndex:slash.location] isEqualToString:[account UID]])
136 const char *node = xmlnode_get_attrib(command,"node");
139 id delegate = [[commands objectForKey:[NSString stringWithUTF8String:node]] objectForKey:@"delegate"];
140 if(delegate && [[delegate nonretainedObjectValue] respondsToSelector:@selector(adHocServer:executeCommand:)]) {
141 AMPurpleJabberAdHocCommand *cmd = [[AMPurpleJabberAdHocCommand alloc] initWithServer:self command:command jid:jid iqid:iqid];
142 [[delegate nonretainedObjectValue] adHocServer:self executeCommand:cmd];